const request = require('base')
const verify = require('./verify')
const synctool = require('synctool')

// 获取用户信息
const getUserInfo = (params) => {
	var {_id, doc, user_id, name = 'a-user'} = params
	doc = doc || user_id || _id || request.common.necessary.User
	if (!doc) {
		return request.getError('缺少用户信息')
	}
	return new Promise((resolve, reject) => {
		request.get({name, doc}).then(res => {
			if (res.data.length === 1) {
				resolve(request.getResult({data: res.data[0]}))
			} else if (res.data.length > 1) {
				reject(request.getError(`用户不唯一`))
			} else {
				reject(request.getError(`用户不存在`))
			}
		}).catch(reject)
	})
}

// 数据库信息中是否满足唯一性
const checkUnique = (params) => { // data：额外的参数。比如验证电话号码，必须还要是否已注销的参数
	var {key, value, name = 'a-user', data} = params
	return new Promise((resolve, reject) => {
		request.get({name, where: {...data, [key]: value}}).then(res => {
			resolve(request.getResult({data: res.data.length === 0}))
		}).catch(reject)
	})
}

// 获取用于显示和修改的用户信息
const getModelOptions = (sence) => {
	return [ // 二维数组，用以分组显示
		[
			{
				title: '头像',
				key: 'avatar',
				componentName: 'upload',
				typeDetail: 'image',
				required: true,
			},
			{
				title: '昵称',
				key: 'nickname',
				componentName: 'input',
				required: true,
			},
			{
				title: '电话',
				key: 'phone',
				componentName: 'input',
				typeDetail: 'phone',
				required: true,
			},
			{
				title: '验证码',
				key: 'code',
				editKey: 'phone', // 和phone字段关联
				componentName: 'input',
				typeDetail: 'verify',
				required: true,
			},
			{
				title: '账号',
				key: 'account' ,
				componentName: 'input',
				placeholder: `请输入账号。最少三位，最长18位`,
				rules: [{pattern: '^[a-zA-Z0-9]{3,18}$', errorMessage: '账号不合法'}],
				required: true,
			},
			{
				title: '密码',
				key: 'password' ,
				componentName: 'input',
				typeDetail: 'password',
				placeholder: `请输入当前密码。初始密码为${request.basedata.InitialPassword}`,
				required: true,
			},
			{
				title: '新密码',
				key: 'new_1' ,
				editKey: 'password',
				componentName: 'input',
				typeDetail: 'password',
				placeholder: '请输入新密码。仅限于大小写字母和数字',
				rules: [{pattern: '^[a-zA-Z0-9]{6,16}$', errorMessage: '密码格式不正确'}],
				required: true,
			},
			{
				title: '新密码',
				key: 'new_2' ,
				editKey: 'password',
				componentName: 'input',
				typeDetail: 'password',
				placeholder: '请再次输入新密码',
				required: true,
			},
			{
				title: '邀请码',
				key: 'invite_code',
				onlyInfo: true, // 要验证唯一
				componentName: 'input',
				required: true,
			}
		]
	]
}

module.exports = {
	getUserInfo,
	checkUnique,
	showUserInfo(params) {
		// 不同场景下对要修改的内容要求不一样
		const {type, doc = request.common.necessary.User, sence} = params
		return new Promise((resolve, reject) => {
			getUserInfo({doc}).then(res => {
				const user = res.data
				const modelOptions = getModelOptions(sence)
				const modelValue = {}, modelRules = {}
				const handleItem = (item) => {
					var {key, title, required, typeDetail, editKey, rules = []} = item
					if (typeDetail !== 'password' || editKey) { // 密码类型以及关联的字段，不显示
						modelValue[key] = user[key]
					}
					if (required) {
						rules.unshift({
							required: true,
							errorMessage: `${title}不能为空`,
							trigger: 'blur'
						})
					}
					modelRules[key] = {rules}
				}
				modelOptions.forEach(child => {
					if (Array.isArray(child)) {
						child.forEach(handleItem)
					} else {
						handleItem(child)
					}
				})
				resolve(request.getResult({user, data: {modelOptions, modelValue, modelRules, passtype: request.basedata.PassType}}))
			}).catch(reject)
		})
	},
	/**
	 * 修改用户信息
	 * 有关联性的要去除掉
	 * 是验证码的，要先验证
	 * 有验证唯一性的，要先验证
	 */
	async updateUserInfo(params) {
		var {_id, doc, sence, user_id, name = 'a-user', data} = params
		doc = doc || user_id || _id || request.common.necessary.User
		var errorString = '' // 最先验证密码输入是否一致
		const dataParams = {}
		if (doc) {
			// 验证手机号。先验证码通过，再验证唯一性
			const verifyPhone = (unique) => {
				return new Promise((resolve, reject) => {
					verify.check(data).then(res => {
						delete data.uuid
						delete data.code
						if (unique) { // 并且验证新的手机号是否不存在
							checkUnique({key: 'phone', value: data.phone, data: {phone_state: {filterType: 'neq', filter: 9}}}).then(res => {
								if (res.data) { // 满足条件
									resolve()
								} else {
									reject(new Error(`电话号码已存在`))
								}
							}).catch(reject)
						} else {
							resolve()
						}
					}).catch(reject)
				})
			}
			if (data.password) { // 修改密码
				const {InitialPassword} = request.basedata
				if (data.new_1 || data.new_2) {
					if (data.new_1 === InitialPassword || data.new_1 === synctool.secret.setPassword(InitialPassword, data.passtype)) {
						errorString = '不能使用初始密码'
					} else {
						if (data.new_1 === data.new_2) {
							if (data.new_1 === data.password) {
								errorString = '输入的新旧密码没有变化'
							} else {
								// 然后验证旧密码是否正确
								if (data.password === InitialPassword || data.password === synctool.secret.setPassword(InitialPassword, data.passtype)) {
									// 不需要验证，直接通过
								} else {
									try { // 验证旧密码
										var res = await request.get({name: 'a-user', doc})
										if (res.data && res.data.length === 1) {
											if (res.data[0].password === data.password) {
												// 验证通过后
											} else {
												errorString = '旧密码输入错误'
											}
										} else {
											errorString = '用户信息错误错误'
										}
									} catch (error) {
										errorString = error.message
									}
								}
								dataParams.password = data.password = data.new_1
								delete data.passtype
							}
						} else {
							errorString = '两次输入的密码不一致'
						}
					}
				} else {
					errorString = '新密码错误'
				}
			} else if (data.phone) { // 修改手机号
				/**
				 * 一定要有验证码！
				 * 并且先验证验证码是否通过，然后验证码新的电话号码时i否唯一
				 */
				if (data.code) {
					try {
						var res = await verifyPhone(true)
						console.log(res)
					} catch (error) {
						errorString = error.message
					}
				} else {
					errorString = '缺少验证码'
				}
			}
			if (!errorString) { // 验证验证码、去掉关联性数据、验证唯一性
				if (sence) {
					const tempArr = Object.keys(data)
					/**
					 * 有关联性的要去除掉
					 * 是验证码的，要先验证
					 * 有验证唯一性的，要先验证
					 */
					const modelOptions = getModelOptions(sence)
					const handleItem = (item) => {
						return new Promise(async (resolve, reject) => {
							if (tempArr.includes(item.key)) {
								if (item.editKey) { // 要删除这些不要的字段
									// 验证码的情况下，要验证
									if (item.typeDetail === 'verify') { // 其它需要处理的验证码情况
										try {
											var res = await verifyPhone(false)
											console.log(res)
											delete data.uuid
										} catch (error) {
											errorString = error.message
										}
									}
									delete data[item.key]
								} else {
									if (item.onlyInfo) { // 验证唯一性
										try {
											var res = await checkUnique({...item.onlyInfo, key: item.key, value: data[item.key]})
											if (res.data) { // 添加验证通过后的数据
												dataParams[item.key] = data[item.key]
											} else {
												errorString = `${item.title}已存在`
											}
										} catch (error) {
											errorString = error.message
										}
									} else {
										dataParams[item.key] = data[item.key]
									}
								}
							}
							if (errorString) {
								reject(request.getError(errorString))
							} else {
								resolve()
							}
						})
					}
					const cycle = async () => {
						for (let i = 0; i < modelOptions.length; i++) {
							if (Array.isArray(modelOptions[i])) {
								for (let j = 0; j < modelOptions[i].length; j++) {
									const item = modelOptions[i][j]
									await handleItem(item)
								}
							} else {
								await handleItem(Array.isArray(modelOptions[i]))
							}
						}
					}
					try {
						await cycle()
					} catch (error) {
						if (typeof(error.message) === 'string') {
							errorString = error.message
						}
					}
				}
			}
		} else {
			errorString = '缺少用户信息'
		}
		return new Promise((resolve, reject) => {
			if (errorString) {
				reject(request.getError(errorString))
			} else {
				request.alert({name, doc, data: dataParams}).then(res => {
					resolve(request.getResult({data: res.data}))
				}).catch(reject)
			}
		})
	},
}